<template>
  <Dialog
    :visible="visible"
    modal
    header="BPMN流程设计器"
    :style="{ width: '95vw', height: '90vh' }"
    :closable="true"
    :draggable="false"
    :maximizable="true"
    @update:visible="$emit('update:visible', $event)"
    @hide="handleClose"
    class="bpmn-designer-dialog"
  >
    <div class="bpmn-designer">
      <!-- 工具栏 -->
      <div class="designer-toolbar">
        <div class="toolbar-left">
          <Button
            icon="pi pi-file"
            label="新建"
            size="small"
            @click="createNewDiagram"
          />
          <Button
            icon="pi pi-folder-open"
            label="打开XML"
            size="small"
            severity="secondary"
            @click="triggerFileInput"
          />
          <Button
            icon="pi pi-save"
            label="保存"
            size="small"
            severity="success"
            @click="saveDiagram"
          />
          <input
            ref="fileInput"
            type="file"
            accept=".xml,.bpmn"
            style="display: none"
            @change="handleFileUpload"
          />
        </div>
        
        <div class="toolbar-right">
          <Button
            icon="pi pi-download"
            label="导出XML"
            size="small"
            severity="secondary"
            @click="exportXml"
          />
          <Button
            icon="pi pi-image"
            label="导出SVG"
            size="small"
            severity="secondary"
            @click="exportSvg"
          />
          <Button
            icon="pi pi-search-plus"
            icon-only
            size="small"
            text
            @click="zoomIn"
            title="放大"
          />
          <Button
            icon="pi pi-search-minus"
            icon-only
            size="small"
            text
            @click="zoomOut"
            title="缩小"
          />
          <Button
            icon="pi pi-refresh"
            icon-only
            size="small"
            text
            @click="resetZoom"
            title="重置缩放"
          />
        </div>
      </div>
      
      <!-- BPMN画布 -->
      <div class="designer-container">
        <div ref="bpmnContainer" class="bpmn-canvas"></div>
        <div v-if="!isModelerReady" class="loading-overlay">
          <i class="pi pi-spin pi-spinner" style="font-size: 2rem;"></i>
          <p>正在加载BPMN设计器...</p>
          <Button
            label="重新初始化"
            size="small"
            severity="secondary"
            @click="retryInit"
            style="margin-top: 16px;"
          />
        </div>
      </div>
    </div>

    <template #footer>
      <div class="dialog-footer">
        <Button
          label="取消"
          severity="secondary"
          @click="handleClose"
        />
        <Button
          label="确定使用"
          severity="primary"
          icon="pi pi-check"
          @click="handleConfirm"
        />
      </div>
    </template>
  </Dialog>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, onUnmounted, nextTick } from 'vue'
import Dialog from 'primevue/dialog'
import Button from 'primevue/button'
import BpmnModeler from 'bpmn-js/lib/Modeler'
import zhCN from './i18n/zh-cn.js'
import ChineseLabelProvider from './plugins/ChineseLabelProvider.js'
import ChineseTranslateProvider from './plugins/ChineseTranslateProvider.js'

interface Props {
  visible: boolean
  initialXml?: string
}

interface Emits {
  (e: 'update:visible', value: boolean): void
  (e: 'save', xml: string): void
  (e: 'close'): void
}

const props = withDefaults(defineProps<Props>(), {
  initialXml: ''
})

const emit = defineEmits<Emits>()

// 引用
const bpmnContainer = ref<HTMLElement | null>(null)
const fileInput = ref<HTMLInputElement | null>(null)

// 状态
const isModelerReady = ref(false)

// BPMN Modeler实例
let modeler: any = null

// 默认的空白BPMN XML
const emptyBpmnXml = `<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
                  xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
                  xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
                  xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
                  id="Definitions_1"
                  targetNamespace="http://bpmn.io/schema/bpmn">
  <bpmn:process id="Process_1" isExecutable="true">
    <bpmn:startEvent id="StartEvent_1"/>
  </bpmn:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds x="179" y="159" width="36" height="36"/>
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn:definitions>`

// 监听visible变化
watch(() => props.visible, async (newVal) => {
  if (newVal) {
    // 等待DOM更新后再初始化
    await nextTick()
    // 再次等待确保容器完全渲染
    setTimeout(async () => {
      if (bpmnContainer.value) {
        await initModeler()
      }
    }, 100)
  }
})

// 初始化BPMN Modeler
  const initModeler = async () => {
    if (!bpmnContainer.value) {
      console.error('BPMN容器元素未找到')
      return
    }
    
    console.log('开始初始化BPMN Modeler...')
    isModelerReady.value = false
    
    try {
      // 清理之前的实例
      if (modeler) {
        modeler.destroy()
        modeler = null
      }
      
      // 确保容器有尺寸
      const container = bpmnContainer.value
      if (container.offsetWidth === 0 || container.offsetHeight === 0) {
        console.warn('容器尺寸为0，等待容器渲染...')
        setTimeout(() => initModeler(), 200)
        return
      }
      
      console.log('容器尺寸:', container.offsetWidth, 'x', container.offsetHeight)
      
      // 创建BPMN Modeler实例并配置汉化
      modeler = new BpmnModeler({
        container: container,
        // 注意：根据bpmn-js最新版本，keyboard.bindTo配置已被移除，键盘绑定现在是隐式的
        // 配置汉化选项
        additionalModules: [
          {
            translate: ['value', zhCN]
          },
          {
            labelProvider: ['type', ChineseLabelProvider]
          },
          ChineseTranslateProvider
        ],
        // 配置翻译服务
        moddleExtensions: {
          bpmn: {
            translate: zhCN
          }
        }
      })
      
      // 注册中文翻译提供者
      const injector = modeler.get('injector')
      const translate = injector.get('translate')
      translate.addProvider(ChineseTranslateProvider)
    
    console.log('BPMN Modeler实例创建成功')
    
    // 导入BPMN XML
    const xmlToImport = props.initialXml || emptyBpmnXml
    console.log('开始导入XML...')
    await modeler.importXML(xmlToImport)
    console.log('XML导入成功')
    
    // 获取画布并居中显示
    const canvas = modeler.get('canvas')
    canvas.zoom('fit-viewport')
    console.log('画布缩放设置完成')
    
    isModelerReady.value = true
    console.log('BPMN Modeler 初始化完成')
  } catch (error) {
    console.error('BPMN Modeler 初始化失败:', error)
    console.error('错误详情:', error.message)
    console.error('错误堆栈:', error.stack)
    isModelerReady.value = true
    // 显示错误信息给用户
    alert(`BPMN设计器初始化失败: ${error.message}`)
  }
}

// 创建新流程图
const createNewDiagram = async () => {
  if (!modeler) return
  
  try {
    await modeler.importXML(emptyBpmnXml)
    const canvas = modeler.get('canvas')
    canvas.zoom('fit-viewport')
    console.log('创建新流程图成功')
  } catch (error) {
    console.error('创建新流程图失败:', error)
  }
}

// 触发文件选择
const triggerFileInput = () => {
  fileInput.value?.click()
}

// 处理文件上传
const handleFileUpload = async (event: Event) => {
  const target = event.target as HTMLInputElement
  const file = target.files?.[0]
  
  if (!file || !modeler) return
  
  try {
    const text = await file.text()
    await modeler.importXML(text)
    const canvas = modeler.get('canvas')
    canvas.zoom('fit-viewport')
    console.log('导入XML成功')
  } catch (error) {
    console.error('导入XML失败:', error)
    alert('导入XML失败，请检查文件格式')
  }
  
  // 重置文件输入
  target.value = ''
}

// 保存流程图
const saveDiagram = async () => {
  if (!modeler) return
  
  try {
    const { xml } = await modeler.saveXML({ format: true })
    console.log('流程图已保存:', xml)
    alert('流程图已保存到内存')
  } catch (error) {
    console.error('保存流程图失败:', error)
  }
}

// 导出XML
const exportXml = async () => {
  if (!modeler) return
  
  try {
    const { xml } = await modeler.saveXML({ format: true })
    
    // 创建下载链接
    const blob = new Blob([xml || ''], { type: 'application/xml' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = `bpmn_diagram_${Date.now()}.xml`
    a.click()
    URL.revokeObjectURL(url)
    
    console.log('导出XML成功')
  } catch (error) {
    console.error('导出XML失败:', error)
  }
}

// 导出SVG
const exportSvg = async () => {
  if (!modeler) return
  
  try {
    const { svg } = await modeler.saveSVG()
    
    // 创建下载链接
    const blob = new Blob([svg || ''], { type: 'image/svg+xml' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = `bpmn_diagram_${Date.now()}.svg`
    a.click()
    URL.revokeObjectURL(url)
    
    console.log('导出SVG成功')
  } catch (error) {
    console.error('导出SVG失败:', error)
  }
}

// 缩放控制
const zoomIn = () => {
  if (!modeler) return
  const canvas = modeler.get('canvas')
  const currentZoom = canvas.zoom()
  canvas.zoom(currentZoom + 0.1)
}

const zoomOut = () => {
  if (!modeler) return
  const canvas = modeler.get('canvas')
  const currentZoom = canvas.zoom()
  canvas.zoom(currentZoom - 0.1)
}

const resetZoom = () => {
  if (!modeler) return
  const canvas = modeler.get('canvas')
  canvas.zoom('fit-viewport')
}

// 处理确认
const handleConfirm = async () => {
  if (!modeler) {
    emit('update:visible', false)
    return
  }
  
  try {
    const { xml } = await modeler.saveXML({ format: true })
    emit('save', xml || '')
    emit('update:visible', false)
  } catch (error) {
    console.error('获取XML失败:', error)
    alert('获取流程XML失败')
  }
}

// 重试初始化
const retryInit = async () => {
  console.log('用户手动重试初始化BPMN设计器')
  await initModeler()
}

// 处理关闭
const handleClose = () => {
  emit('update:visible', false)
  emit('close')
}

// 组件卸载时清理
onUnmounted(() => {
  if (modeler) {
    modeler.destroy()
    modeler = null
  }
})
</script>

<style scoped>
.bpmn-designer {
  display: flex;
  flex-direction: column;
  height: calc(90vh - 120px);
}

.designer-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background: #fafafa;
  border-bottom: 1px solid #e8e8e8;
  flex-shrink: 0;
}

.toolbar-left,
.toolbar-right {
  display: flex;
  gap: 8px;
  align-items: center;
}

.designer-container {
  flex: 1;
  position: relative;
  overflow: hidden;
  background: #f5f5f5;
}

.bpmn-canvas {
  width: 100%;
  height: 100%;
}

.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.9);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
  z-index: 1000;
}

.loading-overlay i {
  color: #1890ff;
}

.loading-overlay p {
  font-size: 14px;
  color: #666;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

/* BPMN设计器全局样式 */
:deep(.bpmn-designer-dialog .p-dialog-content) {
  padding: 0;
  overflow: hidden;
}

/* BPMN.js 默认样式覆盖 */
:deep(.djs-palette) {
  background: white;
  border: 1px solid #e8e8e8;
}

:deep(.djs-context-pad) {
  background: white;
  border: 1px solid #e8e8e8;
}

:deep(.djs-popup) {
  background: white;
  border: 1px solid #e8e8e8;
}
</style>

<style>
/* BPMN.js 必需的全局样式 */
@import 'bpmn-js/dist/assets/diagram-js.css';
@import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
@import 'bpmn-js/dist/assets/bpmn-js.css';

/* 确保BPMN容器有正确的样式 */
.bpmn-canvas {
  position: relative;
  width: 100%;
  height: 100%;
  min-height: 400px;
}

/* BPMN.js 画布样式 */
.bpmn-canvas .djs-container {
  width: 100% !important;
  height: 100% !important;
}

/* 确保调色板可见 */
.djs-palette {
  position: absolute !important;
  top: 20px !important;
  left: 20px !important;
  z-index: 100 !important;
}
</style>
